package thread;

class MyBlockingQueue{
    private String[] elems=null;

    public MyBlockingQueue(int capcity){
        this.elems=new String[capcity];
    }
    private Object locker=new Object();
    private int head=0;
    private int tail=0;
    private int size=0;


    /**
     * 将一个字符串添加到缓存中
     * 如果缓存已满，则线程会等待直到缓存中有空余位置
     *
     * @param s 要添加到缓存中的字符串
     * @throws InterruptedException 如果线程被中断
     */
    public void put(String s) throws InterruptedException {
        synchronized (locker){
            // 检查缓存是否已满，如果已满，则当前线程等待
            while (size==elems.length){
                locker.wait();
            }
            // 将字符串添加到缓存中的尾部
            elems[tail]=s;
            // 更新尾部指针，如果到达末尾则重置为0
            tail++;
            if (tail>=elems.length){
                tail=0;
            }
            // 增加缓存大小
            size++;
            locker.notify();
        }
    }
    /**
     * 从环形缓冲区中取出一个元素
     * 此方法在内部使用监视器模式来处理生产者-消费者问题
     * 当缓冲区为空时，消费者线程将等待直到生产者线程添加元素
     *
     * @return 取出的元素，如果缓冲区为空则返回null
     * @throws InterruptedException 如果线程被中断
     */
    public String take() throws InterruptedException {
        String elem = null;
        // 对缓冲区的访问进行同步，以防止多线程环境下的竞态条件
        synchronized (locker) {
            // 如果缓冲区为空，当前线程等待，直到其他线程添加元素
            while (size == 0) {
                locker.wait();
            }
            // 从头部取出元素，并更新头部索引
            elem=elems[head];
            head++;
            // 如果头部索引达到数组末尾，将其重置为0
            if (head == elems.length) {
                head = 0;
            }
            // 更新缓冲区大小
            size--;
            // 通知可能等待的其他线程，缓冲区状态已改变
            locker.notify();
            return elem;

        }
    }
}




public class ThreadDemo23 {
    public static void main(String[] args) {
        MyBlockingQueue myBlockingQueue=new MyBlockingQueue(100);
        Thread t1=new Thread(()->{
            int n=1;
           while (true){
               try {
                   myBlockingQueue.put(n+" ");
                   System.out.println("生产者"+n);
                   n++;

               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }

           }
        });

        Thread t2=new Thread(()->{
           while (true){
               try {
                   String n=myBlockingQueue.take();
                   System.out.println("消费元素"+n);
                   Thread.sleep(500);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
           }
        });

        t1.start();
        t2.start();
    }
}
